package top.hmtools.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import top.hmtools.RLContext;
import top.hmtools.base.StringTools;
import top.hmtools.pojo.RequestLogBean;
import top.hmtools.random.RandomStringTools;

/**
 * 记录用户请求信息的过滤器
 * @author HyboJ
 *
 */
//@WebFilter(filterName="requestLoggerFilter",urlPatterns="/*")
public class RequestLoggerFilter implements Filter{
	
	private final Logger logger = LoggerFactory.getLogger(RequestLoggerFilter.class);
	
	/**
	 * 本项目工程上下文（其中包括spring上下文）
	 */
	private RLContext rlContext;
	
	/**
	 * 忽略的uri前缀集合
	 */
	private List<String> ignorePrefixes = new ArrayList<String>();
	
	/**
	 * 忽略的uri后缀集合
	 */
	private String ignoreSuffixes = "";

	public RequestLoggerFilter(RLContext rlContext) {
		this.rlContext = rlContext;
		
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		logger.info("过滤器初始化。。。。");

		//完善忽略uri前缀集合
		String ignoreUriPrefixStr = this.rlContext.requestLoggerAutoConfiguration.getIgnoreUriPrefix();
		if(StringTools.isNotBlank(ignoreUriPrefixStr)){
			String[] ignoreUriPrefixArr = ignoreUriPrefixStr.split(",");
			for(String tmp:ignoreUriPrefixArr){
				this.ignorePrefixes.add(tmp);
				logger.info("忽略的uri前缀有："+tmp);
			}
		}
		
		//完善忽略uri后缀集合
		this.ignoreSuffixes = this.rlContext.requestLoggerAutoConfiguration.getIgnoreUriSuffix();
		this.ignoreSuffixes = StringTools.isBlank(this.ignoreSuffixes)?"":this.ignoreSuffixes;
	}

	@Override
	public void doFilter(ServletRequest reqIn, ServletResponse respIn,FilterChain chain) throws IOException, ServletException {
		// 转化 request、response 类型
		HttpServletRequest request=(HttpServletRequest) reqIn;
		HttpServletResponse response = (HttpServletResponse)respIn;
		logger.debug("当前拦截的请求URL是："+request.getRequestURL());

		try {
			//过滤掉不需要记录的指定后缀名的请求
			String requestURI = request.getRequestURI();
			int lastIndexOf = requestURI.lastIndexOf(".");
			if(lastIndexOf>0){
				String suffix = requestURI.substring(lastIndexOf);
				boolean contains = this.ignoreSuffixes.toUpperCase().contains(suffix.toUpperCase());
				if(contains){
					logger.debug("当前URI符合忽略规则："+requestURI+"，含有忽略后缀："+suffix);
					chain.doFilter(request, response);
					return;
				}
			}
			
			//过滤掉不需要记录的指定前缀名的请求
			for(String prefix:this.ignorePrefixes){
				if(requestURI.indexOf(prefix)==0){
					logger.debug("当前URI符合忽略规则："+requestURI+"，含有忽略前缀："+prefix);
					chain.doFilter(request, response);
					return;
				}
			}

			// 组装 请求描述对象实例
			RequestLogBean bean = new RequestLogBean();

			
			String requestID = RandomStringTools.getYyyyMMddHHmmssSSSPrifixShortUuid(8);// 描述请求的标识ID号
			request.setAttribute("requestID", requestID);// 用于渲染view（比如：JSP，或者freemaker）时，从request中获取requestID
			response.addHeader("requestID", requestID);// 用于异步获取数据（比如：Ajax请求获取json）时，从request中获取requestID
			
			bean.setRequestID(requestID);// 请求发起标识ID号
			bean.setRefferURL(request.getHeader("Referer"));// 来源地址
			bean.setRequestDateTime(new Date());// 该次请求时间戳
			bean.setQueryString(request.getQueryString());//URL 中“？”后面的查询参数
			bean.setRequestURI(request.getRequestURI());//uri，相对资源标识

			Map<String, String> headers = new HashMap<String, String>();
			Enumeration headerNames = request.getHeaderNames();
			while (headerNames.hasMoreElements()) {
				Object headerKey = headerNames.nextElement();
				headers.put((String) headerKey,	request.getHeader((String) headerKey));
			}
			bean.setRequestHeaderMap(headers);//http请求中的header信息集合

			String jsonString = JSON.toJSONString(request.getParameterMap());//获取请求参数
//			String characterEncoding = request.getCharacterEncoding();
//			if (StringTools.isBlank(characterEncoding)) {
//				characterEncoding = "UTF-8";
//			}
//			jsonString = new String(jsonString.getBytes("iso8859-1"),	characterEncoding);
			bean.setRequestParamsJsonString(jsonString);//请求参数
			bean.setRequestURL(request.getRequestURL().toString());//请求URL
			bean.setSessionID(request.getSession().getId());//cookie 中携带的sessionId

			chain.doFilter(request, response);

			bean.setResponseCode(String.valueOf(response.getStatus()));//程序处理完后的HTTP状态码
			bean.setResponseDateTime(new Date());//完成响应的时间戳

			boolean isAddToQueueOK = this.rlContext.requestLoggerManager.addRequestLoggerBeanToQueue(bean);
			logger.debug("当前请求信息写入日志信息队列是否OK："+isAddToQueueOK);
			logger.debug(bean.toString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			chain.doFilter(request, response);
		}
	}

	@Override
	public void destroy() {
		logger.info("过滤器消亡。。。");
	}

}
